/**
	Pulsar engine.
	Additional include file. File manager. VFS.

	Copyright (C) 2013-2014 Dmitry Dolgov

	This program is free software; you can redistribute it and/or modify it under the terms of the
	GNU General Public License as published by the Free Software Foundation; either version 2 of
	the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.
*/

namespace pl
{

template <class T> class StdVector;
class Drive;
class FileManagerImpl;
class DriveTranslate;

/*
	Find file interface
*/
class FindFile
{
public:
	/// Release interface
	void release();

	/// Check is searching finished
	virtual bool isFinished() = 0;

	/// Get file name
	virtual const pl::Filepath& getFileName() const = 0;

	/// Get file size
	virtual pl_int64 getFileSize() const = 0;

	/// Get file attributes
	virtual pl_uint32 getFileAttrib() const = 0;

	/// Get file date
	virtual const pl::DateTime& getFileDate(FileDateType type) const = 0;

	/// Find all files with mask and fill vector
	static bool findFiles(StdVector<Filepath>& list, const pl::Filepath& mask, bool recursive);

protected:
	/// Dtor
	virtual ~FindFile() { }
};


/*
	Virtual File System (VFS)
*/
class FileManager
{
friend class Drive;
friend class DriveTranslate;
public:

	/// Create translation disk
	static bool createTranslateDisk(const pl::Filepath& rootPath, const pl::String<4>& prefix);

	/// Get toal disk space
	static pl::FileError getTotalDiskSpace(const pl::Filepath& path, pl_uint64 &nBytes);

	/// Get free disk space
	static pl::FileError getFreeDiskSpace(const pl::Filepath& path, pl_uint64 &nBytes);

	/// Rename a file
	static pl::FileError renameFile(const pl::Filepath& oldName, const pl::Filepath& newName);

	/// Copy file
	static pl::FileError copyFile(const pl::Filepath& oldName, const pl::Filepath& newName, bool bForce = false);

	/// Remove file
	static pl::FileError deleteFile(const pl::Filepath& fileName);

	/// Make a folder
	static pl::FileError makeDir(const pl::Filepath& dirName, bool bAllowRecursive = false);

	/// Remove a folder
	static pl::FileError deleteDir(const pl::Filepath& dirName, pl_uint32 options = 0);

	/// Copy folder
	static pl::FileError copyDir(const pl::Filepath& source, const pl::Filepath& dest, bool bRecursive);

	/// Check file existance
	static pl::FileError checkFileExist(const pl::Filepath& fileName);

	/// Get file attributes
	static pl::FileError getFileAttrib(const pl::Filepath& fileName, pl_uint32& attrib);

	/// Set file attributes
	static pl::FileError setFileAttrib(const pl::Filepath& fileName, pl_uint32 attrib);

	/// Get file size
	static pl::FileError getFileSize(const pl::Filepath& fileName, pl_int64& size);

	/// Set new file size
	static pl::FileError setFileSize(const pl::Filepath& fileName, pl_int64 size);

	/// Get file date (modification/creation/last access)
	static pl::FileError getFileDate(const pl::Filepath& fileName, pl::FileDateType type, pl::DateTime& date);

	/// Set file date (modification/creation/last access)
	static pl::FileError setFileDate(const pl::Filepath& fileName, pl::FileDateType type, const pl::DateTime& date);

	/// Start looking for files
	static pl::FindFile* findFile(const pl::Filepath& mask);

	/// Open file for reading
	static pl::StreamRead* openFileRead(const pl::Filepath& fileName, pl_uint32 shareAndAttrib);

	/// Open file for writing
	static pl::StreamWrite* openFileWrite(const pl::Filepath& fileName, pl_uint32 shareAndAttrib);

	/// Load file into memory (preallocated buffer)
	static pl::FileError loadFileMem(const pl::Filepath& fileName, void* pBuffer, pl_int64& bufSize);

	/// Load file into memory (internal buffer)
	static void* loadFileMem(const pl::Filepath& fileName, pl_int64& pBufSizeActual);

	/// Convert local file name to full file name
	static bool convertToFullPath(pl::Filepath& fileName);

	/// Initialaize manager (internal function, called automatically)
	static bool _init();

	/// Shutdown manager (internal function, called automatically)
	static void _term();


private:
	/// Find drive to accept file (includes virtual drives)
	static Drive* _findDrive(const pl::Filepath& path);

	/// Find physical drive to accept file (with file name translation)
	static Drive* _findHandleDrive(const pl::Filepath& path, pl::Filepath& pathResult);

	/// Platform-speficic implementation
	static FileManagerImpl* _pImpl;
};

} // namespace pl

//
// End of file 'pulsar_file_manager.h'
//
